package mtm.ui.panel;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.security.acl.LastOwnerException;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JPanel;

import mtm.constants.Constants;
import mtm.date.MtmDate;
import mtm.date.MtmMonth;
import mtm.db.DatabaseHandler;
import mtm.db.Job;
import mtm.ui.MainFrame;
import mtm.ui.job.JobFrame;
import mtm.ui.list.DndList;
import mtm.ui.list.JobItem;
import mtm.ui.list.JobList;

/**
 * Month view
 * @author CondorHero89
 *
 */
public class MonthPanel extends JPanel {
	
	public static final int GRID_H_GAP = 2;
	public static final int GRID_V_GAP = 5;
	
	private static MonthPanel instance = null;
	
	private MtmMonth month;
	
	private DndList[] lstDates = new DndList[42];
	private JPanel[] pnlDates = new JPanel[42];
	private JLabel[] lblDays = new JLabel[7];
	
	
	/**
	 * Return a month panel which is correlative with the current month
	 * @return
	 */
	public static MonthPanel getInstance() {
		return instance == null ? new MonthPanel() : instance;
	}
	
	
	/**
	 * Constructor with initial month
	 * @param month
	 */
	private MonthPanel() {
		super();
		instance = this;
		this.month = new MtmMonth();
		
		// set hand cursor for mouse
		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		
		// create days
		for (int i = 0; i < 7; ++i) {
			lblDays[i] = new JLabel(Constants.NORMAL_DAYS[i]);
			lblDays[i].setVerticalAlignment(JLabel.CENTER);
			lblDays[i].setHorizontalAlignment(JLabel.CENTER);
		}
		
		// panel for day labels
		JPanel pnlDays = new JPanel(new GridLayout(1, 7, GRID_H_GAP, 0));
		for (JLabel lbl : lblDays) {
			pnlDays.add(lbl);
		}
		
		// create dates
		int numOfMonths = month.getNumberOfDays();
		int firstDay = month.getFirstDay();
		for (int i = 0; i < lstDates.length; ++i) {
			lstDates[i] = new DndList(DndList.NO_DATE);
		}
		for (int i = 1; i <= numOfMonths; ++i) {
			lstDates[i + firstDay - 2].setDateTitle(i);
		}
		
		// panel for date labels
		JPanel pnlDates = new JPanel(new GridLayout(6, 7, GRID_H_GAP, GRID_V_GAP));
		for (DndList list : lstDates) {
			pnlDates.add(list);
		}
		
		// set layout
		setLayout(new BorderLayout());
		add(pnlDays, BorderLayout.NORTH);
		add(pnlDates, BorderLayout.CENTER);
		
		// load jobs
		loadJobs();
	}
	
	
	/**
	 * Load data of jobs in a month to this panel
	 * @param month
	 */
	public void displayJobsInMonth(MtmMonth month) {
		this.month = month;
		reloadJobs();
	}
	
	
	/**
	 * Reload jobs of this month to display
	 */
	public void reloadJobs() {
		removeAllJobs();
		resetDateLabels();
		loadJobs();
	}
	
	
	/**
	 * Reset date title of labels
	 */
	private void resetDateLabels() {
		int numOfMonths = month.getNumberOfDays();
		int firstDay = month.getFirstDay();
//		for (int i = 0; i < lstDates.length; ++i) {
//			lstDates[i].setDateTitle(DndList.NO_DATE);
//		}
		for (int i = 1; i <= numOfMonths; ++i) {
			lstDates[i + firstDay - 2].setDateTitle(i);
		}
	}
	
	
	/**
	 * Load job from DB
	 */
	public void loadJobs() {
		ArrayList<Job> jobsList = DatabaseHandler.getInstance().getJobsInMonth(month.getYear(), month.getMonth());
		int dateOfJob;
		for (Job job : jobsList) {
			dateOfJob = job.getStartTime().getDate();
			lstDates[dateOfJob + month.getFirstDay() - 2].addItem(new JobItem(job));
		}
	}
	
	
	/**
	 * Remove all jobs from this panel
	 */
	public void removeAllJobs() {
		for (JobList lbl : lstDates) {
			lbl.removeAllJobs();
		}
	}
	
	
	/**
	 * Remove a job
	 * @param job
	 */
	public void removeJob(Job job) {
		int dateOfJob = job.getStartTime().getDate();
		lstDates[dateOfJob - 2 + month.getFirstDay()].removeSelectedItem();
	}
	
	
	/**
	 * Remove a RepeatJob 
	 * @param parentId id of the RepeatJob
	 */
	public void removeRepeatJob(int parentId) {
//		ArrayList<Job> repeatJobsList = 
//			DatabaseHandler.getInstance().getRepeatJobsInMonth(month.getYear(), month.getMonth());
//		for (Job job : repeatJobsList) {
//			if (job.getParentId() == parentId) {
//				lstDates[job.getStartTime().getDate() - 2 + month.getFirstDay()].removeRepeatJob(parentId);
//			}
//		}
//		
		// reload jobs to display
		reloadJobs();
	}
	
	
	/**
	 * Update job when user drag job from a date to another date
	 */
	public void updateJob(Job job, Job oldJob) {
		int dateOfJob = job.getStartTime().getDate();
		int oldDate = oldJob.getStartTime().getDate();
		if (dateOfJob != oldDate) {
			lstDates[oldDate - 2 + month.getFirstDay()].removeSelectedItem();
			lstDates[dateOfJob - 2 + month.getFirstDay()].addItem(new JobItem(job));
		} else {
			lstDates[dateOfJob - 2 + month.getFirstDay()].updateJob(job);
		}
	}
	
	
	/**
	 * Add a job to this 
	 * @param job
	 */
	public void addJob(Job job) {
		// check for time of job is correct for this month
		MtmDate date = new MtmDate(month.getYear(), month.getMonth(), 1);
		MtmDate dateOfJob = job.getStartTime();
		if (date.compareTo(dateOfJob) > 0) {
			return;
		}
		date.setDate(month.getNumberOfDays());
		if (date.compareTo(dateOfJob) < 0) {
			return;
		}
		
		// add job month panel
		int jobDate = job.getStartTime().getDate();
		lstDates[jobDate - 2 + month.getFirstDay()].addItem(new JobItem(job));
	}
}
